package persistencia;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import model.Casilla;
import model.Comodin;
import model.Simple;

public class AdmPersistenciaCasilla {
	private static AdmPersistenciaCasilla instancia;
	private static final String SIMPLE_CASILLA = "Simple";
	private static final String COMODIN_CASILLA = "Comodin";
	private static final String SELECT_CASILLAS = "select * from tpinteractivas.casillas where tipo=? ";
	

	private static final String SELECT_COMODIN_DATA="select codigo,nombre,tipo from tpinteractivas.casillas_relacion rel,tpinteractivas.casillas cas "
			+ "where rel.casillas_codigoRelacion=cas.codigo  and casillas_codigo=?";
	
	private static final String SELECT_LIST_SIMPLES="select * from tpinteractivas.casillas where tipo='"+SIMPLE_CASILLA+"' and Codigo in ";
	private static final String SELECT_LIST_COMODINES = "select * from tpinteractivas.casillas where tipo='"+COMODIN_CASILLA+"' and Codigo in ";
	private static final String ORDER_BY_RELATION=" order by casillas_codigo";
	private static final String INSERT_CASILLA = "Insert into tpinteractivas.casillas (codigo,nombre,tipo) values(?,?,?)";
	private static final String INSERT_CASILLA_COMODIN_RELACION = "Insert into tpinteractivas.casillas_relacion (CASILLAS_CODIGO,CASILLAS_CODIGORELACION) VALUES(?,?) ";
	
	private static final String DELETE_CASILLA_COMODIN_RELACION = "DELETE  FROM tpinteractivas.casillas_relacion ";
	
	private static final String DELETE_CASILLA = "DELETE FROM tpinteractivas.casillas ";
	
	private static final String COUNT_CASILLAS = "SELECT COUNT(*) FROM tpinteractivas.casillas";
	
	
	
	
	
	
	private AdmPersistenciaCasilla() {

	}

	public static synchronized AdmPersistenciaCasilla getInstancia() {
		if (instancia == null)
			instancia = new AdmPersistenciaCasilla();
		return instancia;
	}
	
	
	public boolean insertCasillaSimple(Simple casilla){
		Connection con = PoolConnection.getPoolConnection().getConnection();
		boolean insert=false;
		try {
			PreparedStatement s = con
					.prepareStatement(INSERT_CASILLA);
			s.setInt(1, casilla.getCodigo());
			s.setString(2, casilla.getNombre());
			s.setString(3, casilla.getClass().getSimpleName());
			insert=s.execute();
		
		} catch (SQLException e) {

		}
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return insert;
	}
	
	public boolean insertCasillaComodin(Comodin comodin){
		Connection con = PoolConnection.getPoolConnection().getConnection();
		boolean insert=false;
		try {
			PreparedStatement ps = con.prepareStatement(INSERT_CASILLA);
			ps.setInt(1, comodin.getCodigo());
			ps.setString(2, comodin.getNombre());
			ps.setString(3, comodin.getClass().getSimpleName());
			insert=ps.execute();

			for (Casilla casilla : comodin.getCasillas()) {
				ps = con.prepareStatement(INSERT_CASILLA_COMODIN_RELACION);
				ps.setInt(1, comodin.getCodigo());
				ps.setInt(2, casilla.getCodigo());
				insert = ps.execute();
			}
		} catch (SQLException e) {
			System.out.println(e.getMessage());
		}
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return insert;
	}
	
	public Set<Casilla> selectCasillasSimples() {
		Set<Casilla> respuesta = new HashSet<Casilla>();
		Connection con = PoolConnection.getPoolConnection().getConnection();
		try {
			PreparedStatement s = con.prepareStatement(SELECT_CASILLAS);
			s.setString(1, SIMPLE_CASILLA);
			ResultSet result = s.executeQuery();

			while (result.next()) {
				Integer codigo=result.getInt(1);
				String fruta=result.getString(2);
				Casilla simple = new Simple(codigo,fruta);
				respuesta.add(simple);
			}
		} catch (Exception e) {
			System.out.println();
		}
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return respuesta;
	}
	
	
	public Set<Casilla> selectCasillas() {
		Set<Casilla> respuesta = new HashSet<Casilla>();
		respuesta=selectCasillasSimples();
		
		Connection con = PoolConnection.getPoolConnection().getConnection();
		Integer codigo=-1;
		try {
			PreparedStatement s = con.prepareStatement(SELECT_CASILLAS);
			s.setString(1, COMODIN_CASILLA);
			ResultSet result = s.executeQuery();
			
			Comodin comodin=null;
			while (result.next()) {
					codigo=result.getInt(1);
					String nombre=result.getString(2);
					comodin= new Comodin(codigo,nombre);
					llenarComodin(comodin,con);
					respuesta.add(comodin);
			}
			
		} catch (Exception e) {
			System.out.println();
		}
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return respuesta;
	}

	private void llenarComodin(Comodin comodin,Connection con) throws SQLException {
		PreparedStatement s = con.prepareStatement(SELECT_COMODIN_DATA);
		s.setLong(1, comodin.getCodigo());
		ResultSet result = s.executeQuery();
		while (result.next()) {
			Integer codigo=result.getInt(1);
			String nombre=result.getString(2);
			String tipo=result.getString(3);
			
			if (COMODIN_CASILLA.equals(tipo)){
				Comodin comodinInside=new Comodin(codigo,nombre);
				llenarComodin(comodinInside,con);
				comodin.add(comodinInside);
			}	else	{
				Simple frutaSimple=new Simple(codigo,nombre);
				comodin.add(frutaSimple);
			}
			
		}
	}


	public List<Casilla> getCasillas(List<Integer> casillasId) {
		Connection con = PoolConnection.getPoolConnection().getConnection();
		List<Casilla> casillas= new ArrayList<Casilla>();
		Integer codigo=-1;
		try {
			PreparedStatement s = con.prepareStatement(SELECT_LIST_SIMPLES+createInStatement(casillasId.size()));
			setPrepareStatementIn(s,casillasId);
			ResultSet result=s.executeQuery();
			while (result.next()) {
				Integer id=result.getInt(1);
				String fruta=result.getString(2);
				Casilla simple = new Simple(id,fruta);
				casillas.add(simple);
			}
			
			s = con.prepareStatement(SELECT_LIST_COMODINES+createInStatement(casillasId.size()));
			setPrepareStatementIn(s,casillasId);
			result=s.executeQuery();
			Comodin comodin=null;
			while (result.next()) {
				codigo=result.getInt(1);
				String nombre=result.getString(2);
				comodin= new Comodin(codigo,nombre);
				llenarComodin(comodin,con);
				casillas.add(comodin);
				
			}
			
		} catch (Exception e) {
			System.out.println();
		}		
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return obtenerListaOrdernada(casillas,casillasId);
	}
	
	
	
	private String createInStatement(int questionMarks){
		String result = "(";
		for (int i = 0; i < questionMarks; i++) {
			result = result + "?,";
		}
		result = result.substring(0, result.length() - 1) + ")";
		return result;
	}
	
	
	private void setPrepareStatementIn(PreparedStatement statement,List<Integer> ids) throws SQLException{
		for (int i=0;i<ids.size();i++){
			statement.setInt(i+1, ids.get(i));
		}
	}
	
	private List<Casilla> obtenerListaOrdernada(List<Casilla> casillas,List<Integer> ids){
		List<Casilla> respuesta=new ArrayList<Casilla>();
		for (int i=0;i<ids.size();i++){
			for (Casilla casilla:casillas){
				if (casilla.getCodigo()==ids.get(i)){
					respuesta.add(casilla);
				}
			}
		}
		return respuesta;
	}

	public boolean eliminarCasillas() {
		Connection con = PoolConnection.getPoolConnection().getConnection();
		boolean delete=false;
		try {
			Statement s = con.createStatement();
			delete = s.execute(DELETE_CASILLA_COMODIN_RELACION);
			delete = s.execute(DELETE_CASILLA);
	
			delete=true;
		} catch (SQLException e) {
			System.out.println(e.getMessage());
		}
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return delete;
		
	}

	public Integer getCantidadCasillas() {
		Connection con = PoolConnection.getPoolConnection().getConnection();
		Integer count=0;
		try {
			Statement s = con.createStatement();
			ResultSet rs=s.executeQuery(COUNT_CASILLAS);
			if (rs.next()){
				count=rs.getInt(1);
			}
			
		} catch (SQLException e) {
			System.out.println("Error buscando cantidad jugadas");
		}
		PoolConnection.getPoolConnection().realeaseConnection(con);
		return count;
	}
	
	
	
	
	
}
